﻿using System;
using System.IO;
using System.Reflection;
using System.Runtime.ExceptionServices;
using System.Text;
using System.Threading;
using System.Windows.Forms;

namespace XiphMediaEncoder
{
   static class Program
   {
      /// <summary>
      /// Point d'entrée principal de l'application.
      /// </summary>
      [STAThread]
      static void Main()
      {
         // Add the event handler for handling UI thread exceptions to the event.
         Application.ThreadException += Form_UIThreadException;

         // Set the unhandled exception mode to force all Windows Forms errors to go through our handler.
         Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

         // Add the event handler for handling non-UI thread exceptions to the event. 
         AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         Application.Run(new MainForm());
      }

      [HandleProcessCorruptedStateExceptions]
      private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
      {
         CreateBugReport(e.ExceptionObject as Exception);
      }

      [HandleProcessCorruptedStateExceptions]
      private static void Form_UIThreadException(object sender, ThreadExceptionEventArgs t)
      {
         CreateBugReport(t.Exception);
      }

      private static void CreateBugReport(Exception ex)
      {
         var r = new StringBuilder();
         r.AppendLine(@"<?xml version=""1.0"" encoding=""utf-8""?>");
         r.AppendLine("<BugReport>");
         r.AppendLine("  <Software>");
         r.AppendFormat("    <Name>{0}</Name>{1}", "Xiph Media Encoder", Environment.NewLine);
         r.AppendFormat("    <Version>{0}</Version>{1}", Assembly.GetExecutingAssembly().GetName().Version, Environment.NewLine);
         r.AppendLine("  </Software>");
         r.AppendLine("  <SystemInformations>");
         r.AppendFormat("    <OperatingSystem>{0} ({1} bits)</OperatingSystem>{2}", Environment.OSVersion, Environment.Is64BitOperatingSystem ? 64 : 32, Environment.NewLine);
         r.AppendFormat("    <CommonLanguageRuntime>{0}</CommonLanguageRuntime>{1}", Environment.Version, Environment.NewLine);
         r.AppendFormat("    <WorkingSet>{0}</WorkingSet>{1}", Environment.WorkingSet, Environment.NewLine);
         r.AppendFormat("    <ManagedMemory>{0}</ManagedMemory>{1}", GC.GetTotalMemory(false), Environment.NewLine);
         r.AppendFormat("    <ProcessorCount>{0}</ProcessorCount>{1}", Environment.ProcessorCount, Environment.NewLine);
         r.AppendLine("  </SystemInformations>");

         while (ex != null)
         {
            string stack = ex.StackTrace.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
            string[] lines = stack.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);

            r.AppendLine("  <Exception>");
            r.AppendFormat("    <Type>{0}</Type>{1}", ex.GetType(), Environment.NewLine);
            r.AppendFormat("    <Message>{0}</Message>{1}", ex.Message, Environment.NewLine);
            r.AppendLine("    <StackTrace>");
            foreach (string line in lines)
               r.AppendFormat("      <Method>{0}</Method>{1}", line.Trim(), Environment.NewLine);
            r.AppendLine("    </StackTrace>");
            r.AppendLine("  </Exception>");

            ex = ex.InnerException;
         }

         r.AppendLine("  <Assemblies>");
         foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies())
            r.AppendFormat("    <Assembly>{0}</Assembly>{1}", a, Environment.NewLine);
         r.AppendLine("  </Assemblies>");

         r.AppendLine("</BugReport>");

         string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), Path.ChangeExtension(Path.GetRandomFileName(), ".xml"));
         File.WriteAllText(path, r.ToString(), Encoding.UTF8);
      }
   }
}